"""
@name : 05.互斥锁
@author : wenyao
@projectname: xsfh
"""
#LOCK / RLOCK

#互斥锁： 解决资源争用， 数据读取不一致等

import threading
import time

num = 0
def sum_num(i):
    # lock.acquire()  #加锁
    with lock:
        global num
        time.sleep(0.5)
        num += i
        print(num)
    # lock.release()  #释放锁

lock = threading.RLock()  #锁对象
for i in range(5):
    t = threading.Thread(target=sum_num,args=(i,))
    t.start()


##########死锁
# 1、第一种情况
# Lock 原始锁   获取锁之前不做判断，只到获取到锁位置
# RLock 重入锁  获取锁之前先判断，如果自己所有了锁，那就立即返回
# import threading
# # lock1 = threading.Lock()
# lock1 = threading.RLock()
# lock1.acquire()
# print("lock1 acquire 1")
# #同一个线程，获得原始锁之后，没有释放又去尝试获取原始锁，就是产生死锁
# lock1.acquire()
# print("lock1 acquire 2")
# lock1.release()
# print("lock1 release 1")
# lock1.acquire()
# print("lock1 acquire 2")

#第二种
# from threading import Thread,Lock
# from time import sleep
#
# #账户类
# class Account:
# 	def __init__(self,_id,balance,lock):	#每个账户自带一个锁，只要数字balance要变动，就要提前上锁
# 		self._id = _id
# 		self.balance = balance
# 		self.lock = lock
#
# 	#取钱
# 	def withdraw(self,amount):
# 		self.balance -= amount
#
# 	#存钱
# 	def deposit(self,amount):
# 		self.balance += amount
#
# 	#查看余额
# 	def get_balance(self):
# 		return self.balance
#
# #生成两个账户
# liu = Account('刘志文', 12000, Lock())  # Lock()直接创建了一个锁
# hu = Account('胡宇暄', 9000, Lock())
#
#
# # 转账函数，转账基本原则：谁的账户要动，需要先上锁
# # from_参数为要转出账户,to参数为转入账户
# def transfer(from_, to, amount):
#     # from_账户上锁
#     if from_.lock.acquire():
#         from_.withdraw(amount)  # from_账户减少
#         # sleep(1)
#         print("wait .......")
#         # to账户要动了，也要上锁
#         if to.lock.acquire():
#             to.deposit(amount)  # to 加钱
#             to.lock.release()  # 加钱完毕，解锁
#         # from_账户也转账完毕，解锁
#         from_.lock.release()
#     print('%s给%s转了%d元' % (from_._id, to._id, amount))
#
# #生成两个线程，同时转账
# t1 = Thread(target=transfer,args=(liu,hu,4000))	#Tom给Abby转4000
# t2 = Thread(target=transfer,args=(hu,liu,1500))	#Abby给Tom转2500
# #流程：两个线程同时执行，线程t1给Tom上锁，线程t2给Abby上锁，两个线程都向下走，准备给对方上锁，发现对方已经锁上了，资源互不释放，造成死锁
#
# t1.start()
# t2.start()
# t1.join()
# t2.join()
# print('huyuxuan:',liu.get_balance())
# print('liuzhiwen:',hu.get_balance())
#
# #避免死锁：
# #尽量避免同一个线程对多个Lock进行锁定
# #多个线程需要对多个Lock进行锁定，尽量保证他们以相同的顺序加锁